#ifndef _XYZ_H
#define _XYZ_H
#include "../bulk_storage/bulk_storage.h"
#include "stdio.h"

/**
   \defgroup Cartesian

   Structures for three dimensional cartesian coordinates.

   Fast implementations of chessboard, manhattan and euclidian distance functions are
   avaialable, as is an implementation of general p-norm distance.

   \ingroup Metric
*/

/**
   \addtogroup Cartesian
*/

/*@{*/

struct xyz_float {
  float x;
  float y;
  float z;
};

struct xyz_double {
  double x;
  double y;
  double z;
};

struct xyz_short {
  short x;
  short y;
  short z;
};

struct xyz_int {
  int x;
  int y;
  int z;
};

struct xyz_long {
  long x;
  long y;
  long z;
};


/**
 * Implements euclidian distance.
 *
 * @see xyz_float_p_norm_distance, xyz_float_manhattan_distance, xyz_float_chessboard_distance
 */
double xyz_float_distance(const struct xyz_float * a, const struct xyz_float * b);
double xyz_double_distance(const struct xyz_double * a, const struct xyz_double * b);
double xyz_short_distance(const struct xyz_short * a, const struct xyz_short * b);
double xyz_int_distance(const struct xyz_int * a, const struct xyz_int * b);
double xyz_long_distance(const struct xyz_long * a, const struct xyz_long * b);

double xyz_float_manhattan_distance(const struct xyz_float *a, const struct xyz_float *b);
double xyz_double_manhattan_distance(const struct xyz_double *a, const struct xyz_double *b);
double xyz_int_manhattan_distance(const struct xyz_int *a, const struct xyz_int *b);
double xyz_short_manhattan_distance(const struct xyz_short *a, const struct xyz_short *b);
double xyz_long_manhattan_distance(const struct xyz_long *a, const struct xyz_long *b);

double xyz_float_chessboard_distance(const struct xyz_float *a, const struct xyz_float *b);
double xyz_double_chessboard_distance(const struct xyz_double *a, const struct xyz_double *b);
double xyz_short_chessboard_distance(const struct xyz_short *a, const struct xyz_short *b);
double xyz_int_chessboard_distance(const struct xyz_int *a, const struct xyz_int *b);
double xyz_long_chessboard_distance(const struct xyz_long *a, const struct xyz_long *b);

/**
 *  Implements the p_norm distance.  Some common p_norm distances:
 *
 *  p = 1  Manhattan distance:  |dx| + |dy| + |dz|
 *  p = 2  Euclidian distance:  sqrt(dx*dx+dy*dy+dz*dz)
 *  p = inf Chessboard distance:  max(|dx|, |dy|, |dz|)
 *
 *  For performance reasons, inf is not supported by this implementation.  Call xyz_float_chessboard_distance instead.
 *
 *  @see xyz_float_manhattan_distance, xyz_float_distance xyz_float_chessboard_distance
 *
 */
double xyz_float_p_norm_distance(const struct xyz_float *a, const struct xyz_float *b, const double p);
double xyz_double_p_norm_distance(const struct xyz_double *a, const struct xyz_double *b, const double p);
double xyz_short_p_norm_distance(const struct xyz_short *a, const struct xyz_short *b, const double p);
double xyz_int_p_norm_distance(const struct xyz_int *a, const struct xyz_int *b, const double p);
double xyz_long_p_norm_distance(const struct xyz_long *a, const struct xyz_long *b, const double p);

const struct xyz_float * xyz_float_print(const struct xyz_float * a, FILE * ret);
const struct xyz_double * xyz_double_print(const struct xyz_double * a, FILE * ret);
const struct xyz_short * xyz_short_print(const struct xyz_short * a, FILE * ret);
const struct xyz_int * xyz_int_print(const struct xyz_int * a, FILE * ret);
const struct xyz_long * xyz_long_print(const struct xyz_long * a, FILE * ret);

/*@}*/


#endif //_XYZ_H
